//
// Alain Boucher - 19/03/2008
//
// Fonctions utilitaires pour la transformée de Fourier
// TP du cours de Traitement d'images
//
// Note : Les fonctions ci-dessous ne contiennent pas (volontairement)
//        de commentaires dans le code. Les seuls commentaires sont dans 
//        la facon d'utiliser les fonctions. Modifier les parametres et
//        observer les resultats pour bien comprendre le fonctionnement.
//


#include "ImageGray.h"
#include "Functions.h"
#include "ImageRgb.h"
#include "DiskXFile.h"
#include "tiffDiskXFile.h"
#include "CmdLine.h"
#include "Point.h"
#include "Region.h"
#include "RegLinks.h"
#include "xtprobeImageDiskXFile.h"


//**************************************************************************************
//  Fonction :CONSTRUCTEUR de la class Functions
//  Input    :fenetre active et image de la lib cmugraphics
//            Coordonnée de l'affichage de l'image. Par defaut iX=iY=0
//  Output	/
//**************************************************************************************

Functions::Functions(Image *source,int iSeuil1,int iSeuil2,char *col) {
	//Initialisation des variables

	//F.SetBuffering(true);			//active le double buffer
	NbLiaison=0;
	NbRegion=0;
	NbLiaison=0;

	Seuil1=iSeuil1;
	Seuil2=iSeuil2;

	Height=source->height;	// hauteur et largeur de l'image
	Width =source->width;

	//initialisation tableaux aux dimensions de l'image
	colRed=Allocation();
	colGreen=Allocation();
	colBlue=Allocation();
	colGris=Allocation();
	colSelect=Allocation();
	LabelImage=Allocation();


	//remlissage des tableaux gris red green blue avec les valeurs de chaque pixels
	//256 couleurs

	for(int j=0;j<Height;j++)
             for(int i=0;i<Width;i++)
		{
        		
			colRed[i][j]=source->get(j, i)[0];
			colGreen[i][j]=source->get(j, i)[1];
			colBlue[i][j]=source->get(j, i)[2];
			colGris[i][j]=(colRed[i][j]+colGreen[i][j]+colBlue[i][j])/3;
		}

	if(strcmp(col,"red")==0)
	   for(int j=0;j<Height;j++)
             for(int i=0;i<Width;i++)
		colSelect[i][j]=colRed[i][j];
		
	else
		if(strcmp(col,"green")==0)
		   for(int j=0;j<Height;j++)
		     for(int i=0;i<Width;i++)
			colSelect[i][j]=colGreen[i][j];
		else
			if(strcmp(col,"blue")==0)	
			   for(int j=0;j<Height;j++)
			     for(int i=0;i<Width;i++)
				colSelect[i][j]=colBlue[i][j];
			else
			   for(int j=0;j<Height;j++)
			     for(int i=0;i<Width;i++)
				colSelect[i][j]=colGris[i][j];


}


//**************************************************************************
//  Fonction	:Affichage de l'image en couleur au coords iX et iY
//  Input	:fenetre active et les coordonnées iX et iY
//  Output	:Affichage
//**************************************************************************

void Functions::Afficher_RGB(Image *OutImage) {

    for(int i=0;i<OutImage->width;i++)				//pour tous les pixels
            for(int j=0;j<OutImage->height;j++)
		{
                //on dessine le pixel de la couleur selectionnée
                  int aux = (3*(OutImage->width*j)+(3*i));
             	  OutImage->data[aux]=colRed[i][j];
             	  OutImage->data[aux+1]=colGreen[i][j];
             	  OutImage->data[aux+2]=colBlue[i][j];
                  
		}
        OutImage->updatePixmapFromData();
        
}

//**************************************************************************
//  Fonction	:fonction recursive permettant de mettre à jours les tableaux de couleur après
//			:la segmentation
//  Input		:Region *zone
//  Output	:/
//**************************************************************************

void Functions::Sauvegarde_Image(Region* zone) {

    Point P1,P2;
    
	if(zone==0 )						//Point d'arret
            return;
        
	int Mu,Sigma,Maxmin,Label,NbPixel,i,Red_Mu=0,Green_Mu=0,Blue_Mu=0;

	if(zone->IsFeuille())			//verification si on est sur une feuille
	{

		//appel des caracteristiques de la region
		zone->GetCoord(&P1,&P2);
		zone->GetParam(&Mu,&Sigma,&Maxmin,&NbPixel);
		//GetParam(&Mu,&Tmp,&NbPixel);
		Label=zone->GetLabel();

		//P1.Print();
	      	//P2.Print();
		//printf("NbrePixels= %d \nLabel= %d\n\n",NbPixel,Label);
	

		for(i=P1.GetAbs();i<P2.GetAbs();i++)			//pour tous les pixels de la region
			for(int j=P1.GetOrd();j<P2.GetOrd();j++)
				if(LabelImage[i][j]==Label)		//S'il appartiennent réelement à la region
				{
					Red_Mu+=colRed[i][j];
					Green_Mu+=colGreen[i][j];
					Blue_Mu+=colBlue[i][j];
				
				}		

		//Calcul des valeurs moyennes des couleurs en fonction des nouvelles regions
		if(NbPixel!=0) {

		Red_Mu=int(Red_Mu/NbPixel);
		Green_Mu=int(Green_Mu/NbPixel);
		Blue_Mu=int(Blue_Mu/NbPixel);

		}

		//printf("2 .Red= %d \nGreen= %d\nBlue= %d\n\n",Red_Mu,Green_Mu,Blue_Mu);

		//tests de dépassement à priori inutile
		if(Red_Mu>255)Red_Mu=255;
		if(Green_Mu>255)Green_Mu=255;
		if(Blue_Mu>255)Blue_Mu=255;
		if(Red_Mu<0)Red_Mu=0;
		if(Green_Mu<0)Green_Mu=0;
		if(Blue_Mu<0)Blue_Mu=0;
		if(Mu>255)Mu=255;
		if(Mu<0)Mu=0;

		//On actualise les tableaux des couleurs
		for(i=P1.GetAbs();i<P2.GetAbs();i++)			
			for(int j=P1.GetOrd();j<P2.GetOrd();j++)
				if(LabelImage[i][j]==Label)
				{

					colRed[i][j]=Red_Mu;
					colGreen[i][j]=Green_Mu;
					colBlue[i][j]=Blue_Mu;
					colGris[i][j]=Mu;
				}


	}
	Sauvegarde_Image(zone->GetSousReg1());
	Sauvegarde_Image(zone->GetSousReg2());
	Sauvegarde_Image(zone->GetSousReg3());
	Sauvegarde_Image(zone->GetSousReg4());

}


//**************************************************************************
//  Fonction	:fonction recursive permettant de diviser l'image initiale
//  Input	:Region *zone et les coordonnées de la region
//  Ouput	:Création de l'arbre
//**************************************************************************

void Functions::Division(Region *zone, Point P1,Point P2,char *type) {
      double critere=0;
        int iX1=P1.GetAbs();
        int iY1=P1.GetOrd();
        int iX2=P2.GetAbs();
        int iY2=P2.GetOrd();
        
	critere=getCritere(zone,P1,P2,type);

	
      if(critere==2000000){  
 	 return;	
	}
	//On regarde si l'écart type est inférieur au seuil fixée. S'il est inférieur, on arrète
	//de diviser l'image. Sinon, on divise alors l'image en 4 nouvelles regions

	//printf("%d: Crit = %f \n",NbRegion,critere);

	if(critere>=Seuil1)
	{
	//printf("critère: %f Seuil: %f",critere,Seuil1);
		//On crée un fils et on relance l'algo
               
                Point P12(iX1+(iX2-iX1)/2,iY1+(iY2-iY1)/2);
		zone->AddSousReg1();
		Division(zone->GetSousReg1(),P1,P12,type);

                Point P21(iX1+(iX2-iX1)/2,iY1);
                Point P22(iX2,iY1+(iY2-iY1)/2);
		zone->AddSousReg2();
		Division(zone->GetSousReg2(),P21,P22,type);

                Point P31(iX1,iY1+(iY2-iY1)/2);
                Point P32(iX1+(iX2-iX1)/2,iY2);
		zone->AddSousReg3();
		Division(zone->GetSousReg3(),P31,P32,type);

                Point P41(iX1+(iX2-iX1)/2,iY1+(iY2-iY1)/2);
               	zone->AddSousReg4();
		Division(zone->GetSousReg4(),P41,P2,type);

	}
        
	if(zone->IsFeuille())				//Si c'est une region valide
	{
		RegionTmp.push_back(zone);
		NbRegion++;				//on augmente le nombre de region

		zone->SetLabel(NbRegion);		//on nomme cette region du numero de sa region

		//Et pour tous les pixels de la region on place dans labelImage le nom de la region
		for(int i=iX1;i<iX2;i++)
			for(int j=iY1;j<iY2;j++)
				LabelImage[i][j]=NbRegion;
	} 
}

//**************************************************************************
//  Fonction	: Permet de caluler la variance des pixels dans la region
//  Input	:Region *zone et les coordonnées de la region
//  Ouput	: Variance de la région
//**************************************************************************

double Functions::getCritere(Region *zone, Point P1,Point P2,char *type) {

        double dMu=0,dMaxmin=0,dSigma=0;
	int min,max,diff;
	int iSomme=0,NbPixel=0;
        int iX1=P1.GetAbs();
        int iY1=P1.GetOrd();
        int iX2=P2.GetAbs();
        int iY2=P2.GetOrd();
        min=255;
	for(int i=iX1;i<iX2;i++)
		for(int j=iY1;j<iY2;j++)
		{
		   if(min>colSelect[i][j])			
			min=colSelect[i][j];
			
		}
        max=0;
	for(int i=iX1;i<iX2;i++)
		for(int j=iY1;j<iY2;j++)
		{
		   if(max<colSelect[i][j])			
			max=colSelect[i][j];
			
		}

        diff=max-min;

	//Calcul de MU et de SIGMA de la region

	for(int i=iX1;i<iX2;i++)
		for(int j=iY1;j<iY2;j++)
		{
			iSomme+=colSelect[i][j];
			NbPixel++;
		}
	
	if(NbPixel!=0){

	dMu=double(iSomme)/(NbPixel);

	for(int i=iX1;i<iX2;i++)
		for(int j=iY1;j<iY2;j++)
			dSigma+=((colSelect[i][j]-dMu)*(colSelect[i][j]-dMu));

	dSigma=dSigma/NbPixel;

	dMaxmin=diff;
	
	zone->SetCoord(iX1,iY1,iX2,iY2);				//on entre les paramètres de la region
	zone->SetMin(min);
	zone->SetMax(max);
	zone->SetParametre(dMu,dSigma,dMaxmin,NbPixel); 
	
	//printf("Min =%d  Max=%d  Maxmin =%f\n",min,max,dMaxmin);

	if(strcmp(type,"variance")==0)
		return dSigma;
	else
		if(strcmp(type,"maxmin")==0)
			return dMaxmin;
		else
		  if(strcmp(type,"moyenne")==0)	
		   {    if(NbPixel>5)
				return dMu;   
			else
				return 2000000;
			
		     }
      }

	return 2000000;
}

//**************************************************************************
//  Fonction	:Fonction recurcive de création des voisins des différents regions
//  Input	:Region *zone
//  Output	:/
//**************************************************************************

void Functions::Creation_Voisin(Region *zone)
{
 

	if(zone==0||zone==NULL)			//point d'arret
		return;

	if(zone->IsFeuille())		//si on est sur une feuille
	{
		//	PRINCIPE: grace a notre labelImage, on va tester tous les pixels sur les bordures
		//			et ainsi determiner tous les voisins et créer son vector m_Voisin
		
		//printf("OK");

		Point P1,P2;
		bool bAjout;
		zone->GetCoord(&P1,&P2);
		int LabelRegion2;
		vector<int>Voisin_tmp;
		Voisin_tmp.resize(0);
         
		if(P1.GetOrd()!=0)
		{
			for(int i=P1.GetAbs();i<P2.GetAbs();i++)		//on teste les pixels au dessus de la regon
			{
				LabelRegion2=LabelImage[i][P1.GetOrd()-1];
				bAjout=true;
				for(int j=0;j<int(Voisin_tmp.size());j++)	//on test si le pixel determiner
				{						//appartient deja au voisinnage
					if(Voisin_tmp[j]==LabelRegion2)
						bAjout=false;
				} 
				if(bAjout)								//On l'ajoute s'il n'existe pas dans
					Voisin_tmp.push_back(LabelRegion2);//m_Voisin

			}

		}

		if(P2.GetOrd()!=Height)
		{
			for(int i=P1.GetAbs();i<P2.GetAbs();i++)
			{
				LabelRegion2=LabelImage[i][P2.GetOrd()];
				bAjout=true;
				for(int j=0;j<int(Voisin_tmp.size());j++)
				{
					if(Voisin_tmp[j]==LabelRegion2)
						bAjout=false;
				}
				if(bAjout)
					Voisin_tmp.push_back(LabelRegion2);
			}


		}
		if(P1.GetAbs()!=0)
		{
                    for(int i=P1.GetOrd();i<P2.GetOrd();i++)
			{
				LabelRegion2=LabelImage[P1.GetAbs()-1][i];
				bAjout=true;
				for(int j=0;j<int(Voisin_tmp.size());j++)
				{
					if(Voisin_tmp[j]==LabelRegion2)
						bAjout=false;
				}
				if(bAjout)
					Voisin_tmp.push_back(LabelRegion2);
			}

		}
		if(P2.GetAbs()!=Width)
		{
                    for(int i=P1.GetOrd();i<P2.GetOrd();i++)
			{
				LabelRegion2=LabelImage[P2.GetAbs()][i];
				bAjout=true;
				for(int j=0;j<int(Voisin_tmp.size());j++)
				{
					if(Voisin_tmp[j]==LabelRegion2)
						bAjout=false;
				}
				if(bAjout)
					Voisin_tmp.push_back(LabelRegion2);
			}

		} 
		zone->SetVoisin(Voisin_tmp);
	}  


	Creation_Voisin(zone->GetSousReg1());
	Creation_Voisin(zone->GetSousReg2());
	Creation_Voisin(zone->GetSousReg3());
	Creation_Voisin(zone->GetSousReg4());

}


//**************************************************************************
//  Fonction	:fonction recursive permettant de créer le graph des liaisons
//  Input	:Region *zone
//  Output	:Graph
//**************************************************************************

void Functions::Creation_Graph(Region *zone)
{
	if(zone==0)
		return;
	if(zone->IsFeuille())
	{
		int Label=zone->GetLabel();			//on recupère le numero de la region
		vector<int>VoisinTmp=zone->GetVoisin(); 	//et les voisins

		for(int i=0;i<int(VoisinTmp.size());i++)	//pour tous les voisins
		{
			//On crée la liaison si le numero de la region courrante > à celui de la region voisine
			// => permet d'éviter d'avoir des doublons
			if(VoisinTmp[i]<Label)
			{
				//Crée une nouvelle liaison avec comme parametre les 2 regions voisines
				Graph.push_back(new RegLinks(zone,RegionTmp[VoisinTmp[i]-1]));
				NbLiaison++;
			}
		}
	}
	Creation_Graph(zone->GetSousReg1());
	Creation_Graph(zone->GetSousReg2());
	Creation_Graph(zone->GetSousReg3());
	Creation_Graph(zone->GetSousReg4());

}


//**************************************************************************
//  Fonction	:fonction determinant la liaison avec qui a un sigma le plus faible
//		: =>determine les regions à fusionner
//  Input	:/
//  Output	:le numero de la liaison des 2 regions à supprimer
//**************************************************************************

int Functions::DetMin(char *type)
{
	int Auxi=1000000;
	int value=0;
	int Mu,iSigma,iMaxmin,iMoydiff,NbPixel;
	int iNumLiaison=-1;
	for(int i=0;i<NbLiaison;i++)
	{
		Graph[i]->GetParam(&Mu,&iSigma,&iMaxmin,&iMoydiff,&NbPixel);

		if(strcmp(type,"variance")==0)
        		value=iSigma;
		else	
                  if(strcmp(type,"maxmin")==0)
			value=iMaxmin;
		  else	
                    if(strcmp(type,"moyenne")==0)
			value=iMoydiff;

		if((value < Auxi)&&(value>-1))	{

			Auxi=value;
			iNumLiaison=i;
			//printf("In %s = %d \n",type,value);
		}
	}
	//printf("Out %s = %d \n",type,Auxi);
	return iNumLiaison;

}


//**************************************************************************
//  Fonction	:fonction permmettant de fusionner 2 regions et de mettre à jours le voisinnage
//  Input	:iNumLiaison le numero de la liaison
//  Output	:/
//**************************************************************************

void Functions::Fusion(int iNumLiaison)
{
	int Mu,iSigma,iMaxmin,iMoydiff,NbPixel;
	Region *R1=Graph[iNumLiaison]->GetRegion1();		//on recupère les regions à fusionner
	Region *R2=Graph[iNumLiaison]->GetRegion2();


	//On recupère les parametres de la liaison et on les places dans la region1
	Graph[iNumLiaison]->GetParam(&Mu,&iSigma,&iMaxmin,&iMoydiff,&NbPixel);
	R1->SetParametre(Mu,iSigma,iMaxmin,NbPixel);

	//On recupère les coordonnées des regions
	Point R1_P1,R1_P2,R2_P1,R2_P2;
	R1->GetCoord(&R1_P1,&R1_P2);
	R2->GetCoord(&R2_P1,&R2_P2);

	//et on place dans R1 les points extrèmes des 2 regions
	R1->SetCoord(Mini(R1_P1.GetAbs(),R2_P1.GetAbs()),Mini(R1_P1.GetOrd(),R2_P1.GetOrd()),Maxi(R1_P2.GetAbs(),R2_P2.GetAbs()),Maxi(R1_P2.GetOrd(),R2_P2.GetOrd()));
	R2->SetCoord(-1,-1,-1,-1);

	int LabelR1=R1->GetLabel();
	int LabelR2=R2->GetLabel();

	//On remplace dans le LabelImage tous les pixels qui correspondaient à la region2
	for(int i=R2_P1.GetAbs();i<R2_P2.GetAbs();i++)
		for(int j=R2_P1.GetOrd();j<R2_P2.GetOrd();j++)
			if(LabelImage[i][j]==LabelR2)
				LabelImage[i][j]=LabelR1;


	//**************************************************
	//MISE A JOUR DU GRAPH DES LIAISONS ET DU VOISINNAGE


	//determine le nombre de liaison à modifier ==> Gain de 30% en temps
	//On modifie seulement les liaisons voisines...
                
	int nb_a_modifier=0,VoisinJ;

	for(int j=0;j<R1->GetNbVoisin();j++)
	{
		VoisinJ=R1->GetVoisin(j);
		if(VoisinJ!=LabelR2)
			nb_a_modifier++;
	}
	for(int j=0;j<R2->GetNbVoisin();j++)
	{
		VoisinJ=R2->GetVoisin(j);
		if(VoisinJ!=LabelR1)
			nb_a_modifier++;
	}

	//On supprime la liaison fusionné
	delete Graph[iNumLiaison];
	Graph.erase(Graph.begin()+iNumLiaison);
	NbLiaison--;

	//On supprime le label de la region2 du vecteur voisin de la region1
	for(int i=0;i<R1->GetNbVoisin();i++)
		if(R1->GetVoisin(i)==LabelR2)
			R1->SupVoisin(i);


	//pour toutes les liaisons du graph,
	//Si on a modifié toutes les regions qu'il fallait retucher on quitte le for

	for(int i=0;i<NbLiaison && nb_a_modifier!=0;i++)
	{

		bool LiaisonSup=false;

		int LabelLiaison1=Graph[i]->GetLabelR1();
		int LabelLiaison2=Graph[i]->GetLabelR2();

		//on teste si la region supprimer :LABEL R2 est presente dans les liaisons
		//IsRegion1 correspond à la region1 de la liaison.
		//IsRegion1 correspond à la region2 de la liaison.
		bool IsRegion1=LabelR2==LabelLiaison1;
		bool IsRegion2=LabelR2==LabelLiaison2;
		bool IsRegion_Update=(LabelR1==LabelLiaison1 || LabelR1==LabelLiaison2 ||LabelR2==LabelLiaison1 ||LabelR2==LabelLiaison2);

		if(IsRegion1||IsRegion2||IsRegion_Update)
			nb_a_modifier--;

		if(IsRegion1||IsRegion2)
		{
			bool bLiaisonExistante=false;

			//Est ce que ce label existe deja (dsR1)?
			for(int j=0;j<R1->GetNbVoisin();j++)
			{
				if(IsRegion2)
				{
					if(R1->GetVoisin(j) == Graph[i]->GetLabelR1())
						bLiaisonExistante=true;
				}
				else
				{
					if(R1->GetVoisin(j)== Graph[i]->GetLabelR2())
						bLiaisonExistante=true;
				}

			}
			//Si elle n'existe pas, il faut la rajouter
			if(!bLiaisonExistante)
			{
				if(IsRegion1)
				{
					Graph[i]->SetRegLinks(1,R1);
					R1->AddVoisin(Graph[i]->GetLabelR2());

				}
				else
				{
					Graph[i]->SetRegLinks(2,R1);
					R1->AddVoisin(Graph[i]->GetLabelR1());
				}
			}
			else		//la liaison existe =>il faut la supprimmer
			{

				Graph[i]->SupVoisin(IsRegion1,LabelR2);
				delete Graph[i];
				Graph.erase(Graph.begin()+i);
				i--;							//on supprime une liaison=>il faut decrementer i
				NbLiaison--;					//pour voir toutes les liaisons
				LiaisonSup=true;
			}
		}
		if(IsRegion_Update && LiaisonSup==false)	//On update la liaison si elle n'a pas été
			Graph[i]->UpDate();						//supprimé
	}

}

//**************************************************************************
//  Fonction	:Gestion de la division et de la fusion
//  Input	:la fenetre active et les seuils
//  Output	:/
//**************************************************************************

void Functions::Merge(char *type)
{ 
	printf(" NbRegion= %d  \n",NbRegion);
	
	int Mu,iSigma,iMaxmin,iMoydiff,NbPixel,crit;
	int Min=0;
	Min= DetMin(type);
	//printf(" Minimum= %d  \n",Min);
	if(Min!=-1){
	Graph[Min]->GetParam(&Mu,&iSigma,&iMaxmin,&iMoydiff,&NbPixel);
	//printf(" Ok");
	//printf(" OkMu= %d  type=%s\n",Mu,type);

	if(strcmp(type,"variance")==0){
		crit=iSigma;
	}
	else {
		if(strcmp(type,"maxmin")==0){
			crit=iMaxmin;
		}else {
			if(strcmp(type,"moyenne")==0){
				crit=iMoydiff;
			}
		}	
	}

	//printf(" Critéria= %d  Seuil= %d\n",crit,Seuil2);

	//On fusionne tant que le nombre de region est sup au seuil2
	
	
	while(( crit < Seuil2)&&(NbRegion!=0)&&(Min!=-1))
	{

            	    Fusion(Min);	//Fusion des regions avec le critère le plus faible
		    NbRegion--;
	        
	
		Min= DetMin(type);
		//printf(" Minimum= %d  \n",Min);
		if(Min!=-1){
			Graph[Min]->GetParam(&Mu,&iSigma,&iMaxmin,&iMoydiff,&NbPixel);
			//printf("Mu =%d  MaxMin=%d\n",Mu,iMaxmin);

			if(strcmp(type,"variance")==0){
				crit=iSigma;
			}
			else {
				if(strcmp(type,"maxmin")==0){
					crit=iMaxmin;
				}else {
					if(strcmp(type,"moyenne")==0){
						crit=iMoydiff;
					}
				}	
			}
		}
	//printf("IN Crit= %d  \n",crit);
	}
	//printf("OUT Minimum= %d  \n",Min);
	//on sauvegarde l'image et on libère l'espace mémoire
	Sauvegarde_Image(racine);
	FreeTree(racine);
	FreeGraph();  
   }
}


void Functions::Split(char *type)
{


	racine=new Region();		//racine : NbLiaison de notre arbre :premier objet de class Region
        Point P1(0,0);
        Point P2(Width,Height);

	Division(racine,P1,P2,type);    //division de l'image
	Creation_Voisin(racine);	//creation des voisins
	Creation_Graph(racine);		//creation du graph
	RegionTmp.resize(0);		//on libère l'espace de regionTmp
	
}


void Functions::FreeGraph()
{
	for(int i=0;i<int(Graph.size());i++)
		delete Graph[i];

	Graph.resize(0);
}

void Functions::FreeTree(Region *zone)
{
	if(zone==0)
		return;
	if(zone->IsFeuille())
	{
		delete zone;
		zone=0;
		return;
	}
	FreeTree(zone->GetSousReg1());
	FreeTree(zone->GetSousReg2());
	FreeTree(zone->GetSousReg3());
	FreeTree(zone->GetSousReg4());

	delete zone;
	zone=0;
}

int **Functions::Allocation()
{
	int **tab;
	tab=new int*[Width];


	for(int i=0;i<Width;i++)
		tab[i]=new int[Height];

	return tab;


}

void Functions::Desallocation(int **tab)
{
	if(tab==0)
		return;
	for(int i=0;i<Width;i++)
		delete []tab[i];

	delete []tab;
	tab=0;
}


void Functions::FreeTab()
{
	Desallocation(colRed);
	Desallocation(colGreen);
	Desallocation(colBlue);
	Desallocation(colGris);
	Desallocation(LabelImage);
}

Image *  loadImage(bool verbose,char* image_filename)
{

	Image *source = NULL;
// Création et chargement de l'image
	xtprobeImageDiskXFile *image_file = NULL;
	source = new ImageRgb();	
	source->setBOption("verbose", verbose);

// Choix: xtprobeImageDiskXFile car il permet de travailler avec plusieurs types d'images

	if(!new xtprobeImageDiskXFile(image_filename, "r"))
            return NULL;

        image_file = new xtprobeImageDiskXFile(image_filename, "r");
	source->loadImageXFile(image_file);
	delete image_file;


	if(verbose)
	{
		print("Image info:\n");
		print("   width = %d\n", source->width);
		print("   height = %d\n", source->height);
		print("   format = %s (%d)\n", source->coding, source->n_planes);
	}

return source;
}

//******   Construction du nom de fichier *******//

char *  setTitle(char* string,char* prefix)
{

	char *str = new char[300];
	char *str1 = new char[300];
	int i, j=0;

// Extraction du nom du fichier sans extension

	for (i = 0; string[i] != '\0'; i ++)
	 {
           if(string[i]!='/')
            {
  	     str[j] = string[i];
             j++;
            }
	   else
            {
	    j=0;
             }
         }
	str[j ++] = (char)NULL;

	for (i = 0; str[i] != '.'; i ++)
	 {
          str1[i] = str[i];
         }

        str1[i] = (char)NULL;

	strcat(str1, prefix);
	return str1;
}

void saveImage(Image *InImage, char *name) {

        tiffDiskXFile *image_file = NULL;
	image_file = new tiffDiskXFile(name, "w");	
	image_file->writeHeader(InImage->width, InImage->height);
	image_file->writePixmap(InImage->pixmap);
	delete image_file; 
}
